package com.travel.travel_springboot_web.mapper;

import com.travel.travel_springboot_web.entity.Order;
import com.travel.travel_springboot_web.entity.Address;
import org.apache.ibatis.annotations.*;

import java.util.List;
import java.time.LocalDateTime;

@Mapper
public interface OrderMapper {
    @Insert("INSERT INTO orders (order_no, user_id, total_amount, address_id, status, delivery_person, customer, created_at, updated_at) " +
            "VALUES (#{orderNo}, #{userId}, #{totalPrice}, #{addressId}, 1, #{deliveryPerson}, #{customer}, NOW(), NOW())")
    @Options(useGeneratedKeys = true, keyProperty = "id")
    int insert(Order order);
    
    @Results(id = "orderResultMap", value = {
        @Result(property = "id", column = "id"),
        @Result(property = "orderNo", column = "order_no"),
        @Result(property = "userId", column = "user_id"),
        @Result(property = "totalPrice", column = "total_amount"),
        @Result(property = "addressId", column = "address_id"),
        @Result(property = "status", column = "status"),
        @Result(property = "confirmationStatus", column = "confirmation_status"),
        @Result(property = "deliveryStatus", column = "delivery_status"),
        @Result(property = "deliveryConfirmedAt", column = "delivery_confirmed_at"),
        @Result(property = "customerConfirmedAt", column = "customer_confirmed_at"),
        @Result(property = "deliveryPerson", column = "delivery_person"),
        @Result(property = "customer", column = "customer"),
        @Result(property = "createdAt", column = "created_at"),
        @Result(property = "updatedAt", column = "updated_at"),
        @Result(property = "orderGoods", column = "id",
            many = @Many(select = "com.travel.travel_springboot_web.mapper.OrderGoodsMapper.findByOrderId")),
        @Result(property = "address", column = "address_id",
            one = @One(select = "com.travel.travel_springboot_web.mapper.AddressMapper.findById"))
    })
    @Select("SELECT * FROM orders WHERE id = #{id} AND user_id = #{userId}")
    Order findById(@Param("id") Long id, @Param("userId") Long userId);
    
    @Select("SELECT * FROM orders WHERE user_id = #{userId} ORDER BY created_at DESC")
    @ResultMap("orderResultMap")  // 使用已定义的ResultMap
    List<Order> findByUserId(Long userId);
    
    @Select("SELECT * FROM orders WHERE user_id = #{userId} AND status = #{status} ORDER BY created_at DESC")
    @ResultMap("orderResultMap")  // 使用已定义的ResultMap
    List<Order> findByUserIdAndStatus(@Param("userId") Long userId, @Param("status") Integer status);
    
    @Update("UPDATE orders SET status = #{status}, updated_at = NOW() " +
            "WHERE id = #{orderId} AND user_id = #{userId} AND status = 1")
    boolean updateStatus(@Param("orderId") Long orderId, 
                        @Param("userId") Long userId, 
                        @Param("status") Integer status);
    
    @Select("SELECT COUNT(*) FROM orders WHERE user_id = #{userId}")
    int countByUserId(Long userId);
    
    @Select("SELECT COUNT(*) FROM orders WHERE user_id = #{userId} AND status = #{status}")
    int countByUserIdAndStatus(@Param("userId") Long userId, @Param("status") Integer status);
    
    @Update("UPDATE orders SET status = #{status}, updated_at = NOW() " +
            "WHERE id = #{orderId} AND user_id = #{userId} AND status = 3")  // 只能恢复已取消的订单
    boolean updateStatusFromCanceled(@Param("orderId") Long orderId, 
                                   @Param("userId") Long userId, 
                                   @Param("status") Integer status);
    
    @Select("SELECT * FROM orders ORDER BY created_at DESC")
    @ResultMap("orderResultMap")
    List<Order> findAll();
    
    @Select("SELECT * FROM orders WHERE status = #{status} ORDER BY created_at DESC")
    @ResultMap("orderResultMap")
    List<Order> findByStatus(Integer status);
    
    @Select("SELECT COUNT(*) FROM orders")
    int countAll();
    
    @Select("SELECT COUNT(*) FROM orders WHERE status = #{status}")
    int countByStatus(Integer status);
    
    @Select("SELECT o.*, " +
            "a.name as address_name, a.phone as address_phone, " +
            "a.province as address_province, a.city as address_city, " +
            "a.district as address_district, a.detail as address_detail " +
            "FROM orders o " +
            "LEFT JOIN address a ON o.address_id = a.id " +
            "WHERE o.id = #{id}")
    @Results({
        @Result(property = "id", column = "id"),
        @Result(property = "orderNo", column = "order_no"),
        @Result(property = "userId", column = "user_id"),
        @Result(property = "addressId", column = "address_id"),
        @Result(property = "status", column = "status"),
        @Result(property = "totalPrice", column = "total_amount"),
        @Result(property = "createdAt", column = "created_at"),
        @Result(property = "updatedAt", column = "updated_at"),
        @Result(property = "address.name", column = "address_name"),
        @Result(property = "address.phone", column = "address_phone"),
        @Result(property = "address.province", column = "address_province"),
        @Result(property = "address.city", column = "address_city"),
        @Result(property = "address.district", column = "address_district"),
        @Result(property = "address.detail", column = "address_detail"),
        @Result(property = "orderGoods", column = "id",
            many = @Many(select = "com.travel.travel_springboot_web.mapper.OrderGoodsMapper.findByOrderId"))
    })
    Order findByIdForAdmin(Long id);
    
    @Select("SELECT o.*, " +
            "a.name as address_name, a.phone as address_phone, " +
            "a.province as address_province, a.city as address_city, " +
            "a.district as address_district, a.detail as address_detail " +
            "FROM orders o " +
            "LEFT JOIN address a ON o.address_id = a.id " +
            "WHERE o.id = #{id} AND o.user_id = #{userId}")
    @Results({
        @Result(property = "id", column = "id"),
        @Result(property = "orderNo", column = "order_no"),
        @Result(property = "userId", column = "user_id"),
        @Result(property = "addressId", column = "address_id"),
        @Result(property = "status", column = "status"),
        @Result(property = "totalPrice", column = "total_amount"),
        @Result(property = "createdAt", column = "created_at"),
        @Result(property = "updatedAt", column = "updated_at"),
        @Result(property = "address.name", column = "address_name"),
        @Result(property = "address.phone", column = "address_phone"),
        @Result(property = "address.province", column = "address_province"),
        @Result(property = "address.city", column = "address_city"),
        @Result(property = "address.district", column = "address_district"),
        @Result(property = "address.detail", column = "address_detail"),
        @Result(property = "orderGoods", column = "id",
            many = @Many(select = "com.travel.travel_springboot_web.mapper.OrderGoodsMapper.findByOrderId"))
    })
    Order findByIdAndUserId(@Param("id") Long id, @Param("userId") Long userId);
    
    @Update("UPDATE orders SET confirmed = #{confirmed}, updated_at = NOW() " +
            "WHERE id = #{orderId} AND user_id = #{userId}")
    boolean updateConfirmation(@Param("orderId") Long orderId, 
                               @Param("userId") Long userId, 
                               @Param("confirmed") Integer confirmed);
    
    @Update("UPDATE orders SET customer_status = #{customerStatus}, updated_at = NOW() " +
            "WHERE id = #{orderId} AND user_id = #{userId}")
    boolean updateConfirmationStatus(@Param("orderId") Long orderId, 
                                     @Param("userId") Long userId, 
                                     @Param("customerStatus") Integer customerStatus);
    
    @Update("UPDATE orders SET delivery_confirmed_at = NOW() " +
            "WHERE id = #{orderId} AND user_id = #{userId}")
    boolean updateDeliveryConfirmedAt(@Param("orderId") Long orderId, 
                                     @Param("userId") Long userId);
    
    @Update("UPDATE orders SET customer_confirmed_at = NOW() " +
            "WHERE id = #{orderId} AND user_id = #{userId}")
    boolean updateCustomerConfirmedAt(@Param("orderId") Long orderId, 
                                       @Param("userId") Long userId);
    
    @Update("UPDATE orders SET status = #{status}, updated_at = NOW() " +
            "WHERE id = #{orderId} AND user_id = #{userId}")
    boolean updateOrderStatus(@Param("orderId") Long orderId, 
                              @Param("userId") Long userId, 
                              @Param("status") Integer status);
    
    @Update("UPDATE orders SET delivery_status = #{deliveryStatus}, updated_at = NOW() " +
            "WHERE id = #{orderId} AND user_id = #{userId}")
    boolean updateDeliveryStatus(@Param("orderId") Long orderId, 
                                 @Param("userId") Long userId, 
                                 @Param("deliveryStatus") Integer deliveryStatus);
    
    @Update("UPDATE orders SET customer_status = #{customerStatus}, updated_at = NOW() " +
            "WHERE id = #{orderId} AND user_id = #{userId}")
    boolean updateCustomerStatus(@Param("orderId") Long orderId, 
                                 @Param("userId") Long userId, 
                                 @Param("customerStatus") Integer customerStatus);
    
    @Update("UPDATE orders SET delivery_status = #{deliveryStatus}, " +
            "customer_status = #{customerStatus}, " +
            "delivery_confirmed_at = #{deliveryConfirmedAt}, " +
            "customer_confirmed_at = #{customerConfirmedAt}, " +
            "delivery_person = #{deliveryPerson}, customer = #{customer}, " +
            "updated_at = NOW() " +
            "WHERE id = #{orderId} AND user_id = #{userId}")
    boolean updateOrderConfirmationStatus(@Param("orderId") Long orderId,
                                          @Param("userId") Long userId,
                                          @Param("customerStatus") Integer customerStatus,
                                          @Param("deliveryStatus") Integer deliveryStatus,
                                          @Param("deliveryPerson") String deliveryPerson,
                                          @Param("customer") String customer,
                                          @Param("deliveryConfirmedAt") LocalDateTime deliveryConfirmedAt,
                                          @Param("customerConfirmedAt") LocalDateTime customerConfirmedAt);
    
    @Update("UPDATE orders SET delivery_status = #{deliveryStatus}, " +
            "customer_status = #{customerStatus}, " +
            "delivery_confirmed_at = #{deliveryConfirmedAt}, " +
            "customer_confirmed_at = #{customerConfirmedAt}, " +
            "delivery_person = #{deliveryPerson}, customer = #{customer}, " +
            "updated_at = NOW() " +
            "WHERE id = #{orderId}")
    boolean updateOrderConfirmationStatusByAdmin(@Param("orderId") Long orderId,
                                      @Param("customerStatus") Integer customerStatus,
                                      @Param("deliveryStatus") Integer deliveryStatus,
                                      @Param("deliveryPerson") String deliveryPerson,
                                      @Param("customer") String customer,
                                      @Param("deliveryConfirmedAt") LocalDateTime deliveryConfirmedAt,
                                      @Param("customerConfirmedAt") LocalDateTime customerConfirmedAt);
    
    @Update("UPDATE orders SET status = #{status}, updated_at = NOW() WHERE id = #{orderId}")
    boolean updateOrderStatusByAdmin(@Param("orderId") Long orderId, @Param("status") Integer status);
    
    @Select("<script>" +
            "SELECT * FROM orders " +
            "WHERE 1=1 " +
            "<if test='keyword != null and keyword != \"\"'>" +
            "  AND (order_no LIKE CONCAT('%',#{keyword},'%') " +
            "       OR customer LIKE CONCAT('%',#{keyword},'%') " +
            "       OR delivery_person LIKE CONCAT('%',#{keyword},'%')) " +
            "</if>" +
            "<if test='startDate != null and startDate != \"\"'>" +
            "  AND created_at >= #{startDate} " +
            "</if>" +
            "<if test='endDate != null and endDate != \"\"'>" +
            "  AND created_at &lt;= #{endDate} " +
            "</if>" +
            "ORDER BY created_at DESC" +
            "</script>")
    @ResultMap("orderResultMap")
    List<Order> findAllWithSearch(@Param("keyword") String keyword,
                                @Param("startDate") String startDate,
                                @Param("endDate") String endDate);
    
    @Select("<script>" +
            "SELECT * FROM orders " +
            "WHERE status = #{status} " +
            "<if test='keyword != null and keyword != \"\"'>" +
            "  AND (order_no LIKE CONCAT('%',#{keyword},'%') " +
            "       OR customer LIKE CONCAT('%',#{keyword},'%') " +
            "       OR delivery_person LIKE CONCAT('%',#{keyword},'%')) " +
            "</if>" +
            "<if test='startDate != null and startDate != \"\"'>" +
            "  AND created_at >= #{startDate} " +
            "</if>" +
            "<if test='endDate != null and endDate != \"\"'>" +
            "  AND created_at &lt;= #{endDate} " +
            "</if>" +
            "ORDER BY created_at DESC" +
            "</script>")
    @ResultMap("orderResultMap")
    List<Order> findByStatusWithSearch(@Param("status") Integer status,
                                     @Param("keyword") String keyword,
                                     @Param("startDate") String startDate,
                                     @Param("endDate") String endDate);
    
    @Select("<script>" +
            "SELECT * FROM orders " +
            "WHERE user_id = #{userId} " +
            "<if test='keyword != null and keyword != \"\"'>" +
            "  AND (order_no LIKE CONCAT('%',#{keyword},'%') " +
            "       OR customer LIKE CONCAT('%',#{keyword},'%') " +
            "       OR delivery_person LIKE CONCAT('%',#{keyword},'%')) " +
            "</if>" +
            "<if test='startDate != null and startDate != \"\"'>" +
            "  AND created_at >= #{startDate} " +
            "</if>" +
            "<if test='endDate != null and endDate != \"\"'>" +
            "  AND created_at &lt;= #{endDate} " +
            "</if>" +
            "ORDER BY created_at DESC" +
            "</script>")
    @ResultMap("orderResultMap")
    List<Order> findByUserIdWithSearch(@Param("userId") Long userId,
                                     @Param("keyword") String keyword,
                                     @Param("startDate") String startDate,
                                     @Param("endDate") String endDate);
    
    @Select("<script>" +
            "SELECT * FROM orders " +
            "WHERE user_id = #{userId} AND status = #{status} " +
            "<if test='keyword != null and keyword != \"\"'>" +
            "  AND (order_no LIKE CONCAT('%',#{keyword},'%') " +
            "       OR customer LIKE CONCAT('%',#{keyword},'%') " +
            "       OR delivery_person LIKE CONCAT('%',#{keyword},'%')) " +
            "</if>" +
            "<if test='startDate != null and startDate != \"\"'>" +
            "  AND created_at >= #{startDate} " +
            "</if>" +
            "<if test='endDate != null and endDate != \"\"'>" +
            "  AND created_at &lt;= #{endDate} " +
            "</if>" +
            "ORDER BY created_at DESC" +
            "</script>")
    @ResultMap("orderResultMap")
    List<Order> findByUserIdAndStatusWithSearch(@Param("userId") Long userId,
                                              @Param("status") Integer status,
                                              @Param("keyword") String keyword,
                                              @Param("startDate") String startDate,
                                              @Param("endDate") String endDate);
} 